package com.och.mrcp.server;

import com.och.mrcp.config.MrcpConfig;

import com.och.mrcp.handler.MrcpMessageHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;

/**
 * MRCPv2服务器
 * 处理MRCP消息的传输
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class MrcpServer {
    
    private final MrcpConfig mrcpConfig;
    private final MrcpMessageHandler mrcpMessageHandler;
    
    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;
    private Channel channel;
    private boolean isRunning = false;
    
    @PostConstruct
    public void start() {
        try {
            log.info("Starting MRCPv2 server on port {}", mrcpConfig.getLocalPort());
            
            bossGroup = new NioEventLoopGroup(1);
            workerGroup = new NioEventLoopGroup(4);
            
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, mrcpConfig.getMaxConnections())
                    .childOption(ChannelOption.SO_KEEPALIVE, mrcpConfig.isEnableKeepAlive())
                    .childOption(ChannelOption.TCP_NODELAY, true)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ch.pipeline().addLast(mrcpMessageHandler);
                        }
                    });
            
            // 异步绑定，避免阻塞主线程
            bootstrap.bind(mrcpConfig.getLocalPort()).addListener(future -> {
                if (future.isSuccess()) {
                    channel = ((io.netty.channel.ChannelFuture) future).channel();
                    isRunning = true;
                    log.info("MRCPv2 server started successfully on port {}", mrcpConfig.getLocalPort());
                } else {
                    log.error("Failed to bind MRCPv2 server on port {}: {}", 
                            mrcpConfig.getLocalPort(), future.cause().getMessage());
                    throw new RuntimeException("MRCPv2 server bind failed", future.cause());
                }
            });
            
            log.info("MRCPv2 server started successfully on port {}", mrcpConfig.getLocalPort());
            
        } catch (Exception e) {
            log.error("Failed to start MRCPv2 server: {}", e.getMessage(), e);
            throw new RuntimeException("MRCPv2 server startup failed", e);
        }
    }
    
    @PreDestroy
    public void stop() {
        try {
            log.info("Stopping MRCPv2 server...");
            
            if (channel != null) {
                channel.close().sync();
            }
            
            if (bossGroup != null) {
                bossGroup.shutdownGracefully().sync();
            }
            
            if (workerGroup != null) {
                workerGroup.shutdownGracefully().sync();
            }
            
            isRunning = false;
            log.info("MRCPv2 server stopped successfully");
            
        } catch (Exception e) {
            log.error("Error stopping MRCPv2 server: {}", e.getMessage(), e);
        }
    }
    
    public boolean isRunning() {
        return isRunning;
    }
    
    public int getPort() {
        return mrcpConfig.getLocalPort();
    }
    
    public String getResourceType() {
        return mrcpConfig.getResourceType();
    }
}
